﻿using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;

namespace FollowWindow
{
    public class FollowWindowHelper
    {
        /// <summary>
        /// 主窗体
        /// </summary>
        public IntPtr MainWindow { get; set; }

        /// <summary>
        /// 被跟随的窗体
        /// </summary>
        public IntPtr FllowWindowHwnd { get; set; }

        /// <summary>
        /// 跟随窗体隐藏
        /// </summary>
        private bool IsFllowWindowHide { get; set; }

        /// <summary>
        /// 检测
        /// </summary>
        public int FllowCheckTime { get; set; }

        private CSharpAPIs ApiHelper;

        private IntPtr LastForegroundWindow;

        /// <summary>
        /// 跟随的窗口类名
        /// </summary>
        public string OtherClassName { get; set; }

        /// <summary>
        /// 主窗口状态 0 显示 1隐藏
        /// </summary>
        public int MainWindowStatus { get; set; }

        WindowInteropHelper WindowInterop;

        public Window FollowWindow { get; set; }

        public FollowWindowHelper(Window window)
        {
            FollowWindow = window;

            FllowCheckTime = 100;

            WindowInterop = new WindowInteropHelper(window);

            MainWindow = WindowInterop.Handle;
            ApiHelper = new CSharpAPIs();
        }



        /// <summary>
        /// 根据类名进行跟随
        /// </summary>
        /// <param name="className"></param>
        public void StartByClassName(string className = "Notepad")
        {
            OtherClassName = className;
            Thread thread = new Thread(CheckWork);
            thread.IsBackground = true;
            thread.Start();

        }

        private void CheckWork()
        {
            while (MainWindow != IntPtr.Zero)
            {
                var list = ApiHelper.GetAllDesktopWindows();

                var windows = list.Where(c => c.szClassName == OtherClassName).ToList();

                bool hasShow = false;

                windows.ForEach(c =>
                {
                    WINDOWPLACEMENT info = new();

                    ///是否可视
                    bool isShow = (CSharpAPIs.GetWindowLong(c.hWnd, (int)CSharpAPIs.GWL.GWL_STYLE) & 268435456) != 0;

                    if (isShow)
                    {
                        ///1是显示，2最小化，3最大化
                        if (CSharpAPIs.GetWindowPlacement(c.hWnd, ref info))
                        {
                            if (info.showCmd == 1)
                            {
                                hasShow = true;



                                SetWindowFollow(c);
                            }
                        }
                    }
                });


                if (!hasShow)
                {
                    if (MainWindowStatus != 1)
                    {
                        CSharpAPIs.ShowWindow(MainWindow, 0);
                        MainWindowStatus = 1;
                        IsFllowWindowHide = true;
                    }
                }

                Thread.Sleep(FllowCheckTime);
            }

        }

        /// <summary>
        /// 设置跟随
        /// </summary>
        /// <param name="hwnd"></param>
        private void SetWindowFollow(CSharpAPIs.WindowInfo info)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                WindowInterop.Owner = info.hWnd;
            });

            //相同窗口不需要设置
            if (FllowWindowHwnd != info.hWnd)
            {
                FllowWindowHwnd = info.hWnd;
            }

            //是否隐藏
            if (MainWindowStatus == 1)
            {
                CSharpAPIs.ShowWindow(MainWindow, 1);
                MainWindowStatus = 0;
            }

            //判断窗体是否被激活
            if (CSharpAPIs.GetForegroundWindow() != LastForegroundWindow)
            {

                LastForegroundWindow = CSharpAPIs.GetForegroundWindow();

                //没有被隐藏
                if (IsFllowWindowHide == false)
                {
                    //判断是否隐藏
                    if (LastForegroundWindow != MainWindow && LastForegroundWindow != info.hWnd)
                    {
                        IsFllowWindowHide = true;
                    }


                }
                //被隐藏
                else
                {

                    if (LastForegroundWindow == info.hWnd)
                    {
                        IsFllowWindowHide = false;
                        CSharpAPIs.SetForegroundWindow(MainWindow);
                    }
                }


            }


            StartFollow(info);
        }

        /// <summary>
        /// 跟随
        /// </summary>
        /// <param name="info"></param>
        private void StartFollow(CSharpAPIs.WindowInfo info)
        {
            if (CSharpAPIs.GetForegroundWindow() != MainWindow)
            {

                int width = 0;
                Application.Current.Dispatcher.Invoke(() =>
                {
                    width = (int)FollowWindow.Width;
                });

                //这边自己调整位置和大小就行了
                CSharpAPIs.MoveWindow(MainWindow, info.X - width, info.Y, width, info.Height, false);
            }
        }
    }
}
